(ns lensfield.webapp.sparql
   (:require [lensfield.triplestore :as ts]
             [lensfield.webapp.helpers :as hps])
   (:import (java.io ByteArrayOutputStream File)
            (org.openrdf.query BooleanQuery GraphQuery GraphQueryResult QueryLanguage QueryResultUtil TupleQuery)
            (org.openrdf.query.resultio.sparqlxml SPARQLBooleanXMLWriter SPARQLResultsXMLWriter)
            (org.openrdf.model Statement)
            (org.openrdf.rio.rdfxml RDFXMLWriter)))

(defmulti perform-query class)

(defmethod perform-query BooleanQuery [#^BooleanQuery q]
   (with-open [os (ByteArrayOutputStream.)]
      (let [w (SPARQLBooleanXMLWriter. os)]
         (do
            (. w write (. q evaluate)))
         (. os toString))))
         
(defmethod perform-query GraphQuery [#^GraphQuery q]
   (with-open [os (ByteArrayOutputStream.)]
      (let [w (RDFXMLWriter. os)
            gqr (. q evaluate)]
         (do
            (. w startRDF)
            (doseq [s (hps/iterator-to-vector gqr)] (. w handleStatement s))
            (. gqr close)
            (. w endRDF)
            (. os toString)))))
            
(defmethod perform-query TupleQuery [#^TupleQuery q]
   (with-open [os (ByteArrayOutputStream.)]
      (let [w (SPARQLResultsXMLWriter. os)]
         (do
            (QueryResultUtil/report (. q evaluate) w))
         (. os toString))))

(defn sparql-query
   [ts-dir query-str]
   (ts/with-repo-connection ts-dir
      (fn [con] (let [query (. con prepareQuery QueryLanguage/SPARQL query-str)]
         (perform-query query)))))